// Fill out your copyright notice in the Description page of Project Settings.


#include "SHotChunkSettings.h"
#include "SlateOptMacros.h"
#include "SBoxPanel.h"
#include "SButton.h"
#include "SEditableTextBox.h"
#include "IDesktopPlatform.h"
#include "SlateApplication.h"
#include "DesktopPlatformModule.h"
#include "CoreGlobals.h"
#include "SHotChunkPlatformRow.h"
#include "FileManager.h"
#include "Interfaces/ITargetPlatformManagerModule.h"
#include "Interfaces/ITargetPlatform.h"
#include "PlatformFilemanager.h"
#include "EditorStyleSet.h"


#define LOCTEXT_NAMESPACE "SHotChunkSettings"

BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SHotChunkSettings::Construct(const FArguments& InArgs)
{


	ChildSlot
		[
			SNew(SVerticalBox)

			+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		[
			SNew(SHorizontalBox)

			+ SHorizontalBox::Slot()
		.FillWidth(1.0)
		.Padding(0.0f, 4.0f, 0.0f, 0.0f)
		[
			// repository path text box
			SAssignNew(HttpChunkInstallDirectoryTextBox, SEditableTextBox)
			.OnTextCommitted(this, &SHotChunkSettings::HandleHttpChunkInstallDirectoryTextCommitted)
		.OnTextChanged(this, &SHotChunkSettings::HandleHttpChunkInstallDirectoryTextChanged)
		]

	+ SHorizontalBox::Slot()
		.AutoWidth()
		.HAlign(HAlign_Right)
		.Padding(4.0, 0.0, 0.0, 0.0)
		[
			// browse button
			SNew(SButton)
			.ContentPadding(FMargin(6.0, 2.0))
		.IsEnabled(true)
		.Text(LOCTEXT("BrowseButtonText", "Browse..."))
		.ToolTipText(LOCTEXT("BrowseButtonToolTip", "Browse for the Http Chunk Install Data directory"))
		.OnClicked(this, &SHotChunkSettings::HandleHttpChunkInstallBrowseButtonClicked)
		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		.MaxHeight(256.0f)
		[
			SNew(SBorder)
			.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		.Padding(8.0f)
		[
			SNew(SVerticalBox)
			+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SAssignNew(PlatformsView, SListView<TSharedPtr<FString>>)
			.HeaderRow(
				SNew(SHeaderRow)
				.Visibility(EVisibility::Collapsed)

				+ SHeaderRow::Column("PlatformName")
				.DefaultLabel(LOCTEXT("PlatformNameColumnHeader", "Platform"))
				.FillWidth(1.0f)
			)
		.ItemHeight(16.0f)
		.ListItemsSource(&PlatformList)
		.OnGenerateRow(this, &SHotChunkSettings::HandlePlatformViewGenerateRow)
		.SelectionMode(ESelectionMode::None)
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		.HAlign(HAlign_Right)
		[

			// refesh button
			SNew(SButton)
			.ContentPadding(FMargin(6.0, 2.0))
		.IsEnabled(true)
		.Text(LOCTEXT("RefreshButtonText", "Refresh..."))
		.ToolTipText(LOCTEXT("RefreshButtonToolTip", "Refresh Platform in the Http Chunk Install Data directory"))
		.OnClicked(this, &SHotChunkSettings::RefreshPlatformsView)

		]


		]
		]

	+ SVerticalBox::Slot()
		.AutoHeight()
		.Padding(0.0, 4.0, 0.0, 0.0)
		.HAlign(HAlign_Right)
		[

			// refesh button
			SNew(SButton)
			.ContentPadding(FMargin(6.0, 2.0))
		.IsEnabled(true)
		.Text(LOCTEXT("RehashButtonText", "ReHash..."))
		.ToolTipText(LOCTEXT("RehashButtonToolTip", "Rehash Pak in the Http Chunk Install Data directory"))
		//.OnClicked(this, &SHotChunkSettings::RefreshPlatformsView)

		]


		];

	// get the http install diretioy in the config
	FString HttpChunkInstallDataDirectory;
	GConfig->GetString(
		TEXT("/Script/UnrealEd.ProjectPackagingSettings"),
		TEXT("HttpChunkInstallDataDirectory"),
		HttpChunkInstallDataDirectory,
		GGameIni
	);

	if (!HttpChunkInstallDataDirectory.IsEmpty())
	{
		HttpChunkInstallDataDirectory.RemoveAt(0, 7);
		HttpChunkInstallDataDirectory.RemoveAt(HttpChunkInstallDataDirectory.Len() - 2, 2);
		HttpChunkInstallDirectoryTextBox->SetText(FText::FromString(HttpChunkInstallDataDirectory));
	}

}



END_SLATE_FUNCTION_BUILD_OPTIMIZATION



FReply SHotChunkSettings::HandleHttpChunkInstallBrowseButtonClicked()
{
	IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
	if (DesktopPlatform)
	{
		TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().FindWidgetWindow(AsShared());
		void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) ? ParentWindow->GetNativeWindow()->GetOSWindowHandle() : nullptr;

		FString FolderName;
		const bool bFolderSelected = DesktopPlatform->OpenDirectoryDialog(
			ParentWindowHandle,
			LOCTEXT("RepositoryBrowseTitle", "Choose a repository location").ToString(),
			HttpChunkInstallDirectoryTextBox->GetText().ToString(),
			FolderName
		);

		if (bFolderSelected)
		{
			if (!FolderName.EndsWith(TEXT("/")))
			{
				FolderName += TEXT("/");
			}

			HttpChunkInstallDirectoryTextBox->SetText(FText::FromString(FolderName));

		}
	}

	return FReply::Handled();
}


void SHotChunkSettings::HandleHttpChunkInstallDirectoryTextChanged(const FText& InText)
{
	RefreshPlatformsView();
}


void SHotChunkSettings::HandleHttpChunkInstallDirectoryTextCommitted(const FText& InText, ETextCommit::Type CommitInfo)
{
	if (CommitInfo == ETextCommit::OnEnter)
		RefreshPlatformsView();
}

FReply SHotChunkSettings::RefreshPlatformsView()
{
	PlatformList.Reset();

	FString HttpChunkInstallDataDirectory = HttpChunkInstallDirectoryTextBox->GetText().ToString();
	if (!HttpChunkInstallDataDirectory.IsEmpty() && IFileManager::Get().DirectoryExists(*HttpChunkInstallDataDirectory))
	{
#if 0

		IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

		class FHotChunkVisitor : public IPlatformFile::FDirectoryVisitor
		{
		public:
			FHotChunkVisitor()
			{
				TArray<ITargetPlatform*> TargetPlatforms = GetTargetPlatformManager()->GetTargetPlatforms();
				for (auto TargetPlatform : TargetPlatforms)
					AllPlatforms.Add(TargetPlatform->PlatformName());
			}

			virtual bool Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory) override
			{
				UE_LOG(LogTemp, Log, TEXT("HotChunk FHotChunkVisitor [%s]"), FilenameOrDirectory);

				if (bIsDirectory && AllPlatforms.Contains(FilenameOrDirectory))
				{
					Directories.Add(FilenameOrDirectory);
				}
				return true;
			}

			TArray<FString> Directories;

			TArray<FString> AllPlatforms;
		};

		TArray<FString> PlatformPaths;
		FHotChunkVisitor Visitor;
		PlatformFile.IterateDirectoryRecursively(*HttpChunkInstallDataDirectory, Visitor);
		for (auto Directory : Visitor.Directories)
			PlatformPaths.AddUnique(Directory);

#endif

		TArray<FString> AllPlatforms;
		TArray<ITargetPlatform*> TargetPlatforms = GetTargetPlatformManager()->GetTargetPlatforms();
		for (auto TargetPlatform : TargetPlatforms)
			AllPlatforms.Add(TargetPlatform->PlatformName());

		TArray<FString> PlatformDirectories;
		IFileManager::Get().FindFiles(PlatformDirectories, *(HttpChunkInstallDataDirectory / TEXT("*")), false, true);
		for (auto PlatformDirectory : PlatformDirectories)
			if (AllPlatforms.Contains(PlatformDirectory))
				PlatformList.Add(MakeShareable(new FString(PlatformDirectory)));

	}

	PlatformsView->RequestListRefresh();

	return FReply::Handled();
}

TSharedRef<ITableRow> SHotChunkSettings::HandlePlatformViewGenerateRow(TSharedPtr<FString> PlatformName, const TSharedRef<STableViewBase>& OwnerTable)
{
	return SNew(SHotChunkPlatformRow, this)
		.PlatformName(PlatformName)
		.OwnerTableView(OwnerTable);
}

void SHotChunkSettings::AddSelectPlatform(const FString& InPlatform)
{
	if (!SelectPlatforms.Contains(InPlatform))
		SelectPlatforms.Add(InPlatform);
}

void SHotChunkSettings::RemoveSelectPlatform(const FString& InPlatform)
{
	if (SelectPlatforms.Contains(InPlatform))
		SelectPlatforms.Remove(InPlatform);
}

const TArray<FString>& SHotChunkSettings::GetAllSelectPlatforms()
{
	return SelectPlatforms;
}

void SHotChunkSettings::ClearAllSelectPlatforms()
{
	if (SelectPlatforms.Num() > 0)
		SelectPlatforms.Reset();
}

#undef LOCTEXT_NAMESPACE